﻿using DVM.DV.Extensions;
using DVM.DV.Model;
using System.Collections.Concurrent;
using System.Reflection;

namespace DVM.DV.Factory
{
    public class QueryFactory
    {

        private static QueryFactory Instance = null;
        private static readonly object obj = new object();
        /// <summary>
        /// 使用单例，防止对象多次创建初始化
        /// </summary>
        /// <returns></returns>
        public static QueryFactory GetInstance()
        {
            //双重锁定
            if (Instance == null)//只有为null需要实例化处理时才进行加锁，提高性能避免不必要的等待
            {
                lock (obj)
                {
                    if (Instance == null)//避免其他线程等待锁释放期间有线程已经实例化，从而造成多个实例
                        Instance = new QueryFactory();
                }
            }
            return Instance;
        }


        /// <summary>
        /// 查询字段的类集合
        /// </summary>
        public static ConcurrentDictionary<string, ReflectionClassInfo> FieldQueryTypeDic = new ConcurrentDictionary<string, ReflectionClassInfo>();


        private QueryFactory()
        {
            Assembly[] allAssembly = AppDomain.CurrentDomain.GetAssemblies();
            foreach (var assembly in allAssembly)
            {
                var types = assembly.GetTypes().Where(x => (x?.BaseType?.IsGenericType ?? false) && x.GetInterfaces().Count() > 0).ToList();

                foreach (var type in types)
                {
                    if (type == null)
                        continue;
                    var genericArguments = type.BaseType?.GetGenericArguments();
                    if (genericArguments == null || !genericArguments.Any())
                        continue;
                    var attributions = type.GetCustomAttributes(typeof(PropertySetAttribute), false);
                    if (attributions == null || attributions.Length == 0)
                        continue;
                    var attribution = attributions[0] as PropertySetAttribute;
                    if (attribution == null || string.IsNullOrWhiteSpace(attribution.SetPropertyName))
                        continue;
                    var fieldName = attribution.SetPropertyName;
                    var reflectionClassInfo = ReflectionClassInfo.CreateInstance(type);
                    if (!FieldQueryTypeDic.ContainsKey(fieldName))
                        FieldQueryTypeDic.TryAdd(fieldName, reflectionClassInfo);
                }
            }
        }


        /// <summary>
        /// 设置字段值
        /// </summary>
        /// <param name="fieldName"></param>
        public IDMContext? CreateContext(string fieldName, InitInfo initInfo)
        {
            if (!FieldQueryTypeDic.ContainsKey(fieldName))
                return null;
            var fieldQueryType = FieldQueryTypeDic[fieldName];
            fieldQueryType.constructorArgs = new[] { initInfo };
            return (IDMContext)fieldQueryType.ClassObj; ;
        }
    }
}
